Spring Security এর একটি গুরুত্বপূর্ণ দিক হল এর নিরাপত্তা ফিচারগুলি সঠিকভাবে কাজ করছে কিনা তা পরীক্ষা করা এবং সমস্যা হলে তা ডিবাগ করা। নিরাপত্তা সংক্রান্ত ত্রুটি যদি সঠিকভাবে চিহ্নিত না করা হয়, তবে তা অ্যাপ্লিকেশনকে সুরক্ষিত রাখার জন্য বিপজ্জনক হতে পারে। এখানে আমরা Spring Security-এর জন্য Testing এবং Debugging কৌশলগুলো আলোচনা করব।
Spring Security Testing
Spring Security এর নিরাপত্তা ফিচারগুলোর পরীক্ষা করার জন্য কিছু নির্দিষ্ট টেস্টিং পদ্ধতি এবং টুলস রয়েছে যা ব্যবহারকারীর অনুমতি এবং অ্যাক্সেস নিয়ন্ত্রণের সঠিকতা পরীক্ষা করতে সহায়ক।
1. Spring Security Integration Testing
Spring Security-তে নিরাপত্তা পরীক্ষার জন্য integration tests লিখতে হয়, যেখানে আপনি সিস্টেমের বিভিন্ন অংশ একত্রে পরীক্ষা করবেন, যেমন Authentication এবং Authorization। Spring Boot এ @SpringBootTest annotation ব্যবহার করে এই টেস্টগুলি লিখতে পারেন।
Spring Security Test Dependencies
যেকোনো Spring Security টেস্টিং করার আগে প্রয়োজনীয় dependency গুলি pom.xml ফাইলে যুক্ত করুন:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
2. Authentication Test
Spring Security-তে Authentication পরীক্ষা করতে @WebMvcTest অথবা @SpringBootTest ব্যবহার করে HTTP request এর মাধ্যমে পরীক্ষা করা যেতে পারে।
Example: Authentication Test
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@SpringBootTest
public class AuthenticationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testAuthentication() throws Exception {
mockMvc.perform(get("/admin"))
.andExpect(MockMvcResultMatchers.status().isUnauthorized()); // Expect Unauthorized for unauthenticated user
}
}
এখানে, /admin URL কে Unauthorized হিসাবে পরীক্ষা করা হচ্ছে যখন ব্যবহারকারী প্রমাণিত (authenticated) নয়।
3. Authorization Test
Authorization পরীক্ষা করার জন্য আপনি নিশ্চিত করতে পারেন যে নির্দিষ্ট রোল বা পারমিশন ছাড়া কোনো ব্যবহারকারী সংরক্ষিত URL অ্যাক্সেস করতে পারবে না।
Example: Authorization Test
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@SpringBootTest
public class AuthorizationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testAdminAuthorization() throws Exception {
mockMvc.perform(get("/admin"))
.andExpect(MockMvcResultMatchers.status().isForbidden()); // Expect Forbidden for non-admin user
}
}
এখানে /admin URL-এর জন্য Forbidden error আসবে যদি ব্যবহারকারী ADMIN রোলের অধিকারী না হয়।
4. Testing Custom Security Logic
যদি আপনি কাস্টম নিরাপত্তা লজিক (যেমন custom UserDetailsService, custom authentication filter) ব্যবহার করেন, তাহলে সেই লজিকের উপর ভিত্তি করে টেস্ট লিখতে হবে।
Example: Custom UserDetailsService Test
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.User;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@SpringBootTest
public class CustomUserDetailsServiceTest {
@Autowired
private UserDetailsService userDetailsService;
@Test
public void testLoadUserByUsername() {
User user = (User) userDetailsService.loadUserByUsername("testuser");
assertNotNull(user);
assertEquals("testuser", user.getUsername());
}
}
এখানে, CustomUserDetailsService-এর মাধ্যমে ব্যবহারকারীর তথ্য পরীক্ষা করা হচ্ছে।
Spring Security Debugging
Spring Security-এর মাধ্যমে সুরক্ষা সমস্যা সমাধান এবং ডিবাগ করার জন্য কিছু কার্যকরী কৌশল রয়েছে। যখন আপনি Spring Security ব্যবহার করছেন এবং সমস্যা সম্মুখীন হচ্ছেন, তখন কিছু নির্দিষ্ট ডিবাগিং কৌশল ব্যবহার করতে পারেন।
1. Spring Security Debugging Mode
Spring Security ডিবাগিং সহজ করার জন্য একটি ডিবাগিং মোড প্রদান করে, যা বিস্তারিত লগ তথ্য প্রদর্শন করে। আপনি Spring Security-তে ডিবাগিং সক্ষম করতে application.properties বা application.yml ফাইলে নিম্নলিখিত কনফিগারেশন ব্যবহার করতে পারেন:
logging.level.org.springframework.security=DEBUG
এটি Spring Security-এর ভিতরের কার্যকলাপ সম্পর্কে বিশদ লগ তৈরি করবে, যেমন:
- Authentication প্রক্রিয়া
- Authorization চেক
- Security Filter Chains
2. Debugging Authentication and Authorization
Spring Security-এর SecurityContextHolder ক্লাস ব্যবহার করে আপনি লগইন হওয়া ব্যবহারকারীর প্রমাণীকরণ এবং অনুমতি সম্পর্কে ডিবাগ করতে পারেন।
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
public class SecurityDebugging {
public void printAuthenticationDetails() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
System.out.println("Authenticated User: " + authentication.getName());
System.out.println("Roles: " + authentication.getAuthorities());
} else {
System.out.println("No authenticated user found.");
}
}
}
এই কোডটি, লগইন করা ব্যবহারকারীর তথ্য (যেমন নাম এবং রোল) প্রিন্ট করবে।
3. Inspecting HTTP Headers
নিরাপত্তা সম্পর্কিত কিছু তথ্য যেমন JWT token বা Authorization header পরীক্ষা করতে আপনি HTTP request এর headers দেখতে পারেন। এটি করতে আপনি Spring MVC MockMvc ব্যবহার করে HTTP request পরীক্ষা করতে পারেন।
Example: Inspecting Headers
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@SpringBootTest
public class HeaderInspectionTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testInspectHeaders() throws Exception {
mockMvc.perform(get("/admin")
.header("Authorization", "Bearer your-jwt-token"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(result -> {
System.out.println(result.getResponse().getHeader("Authorization"));
});
}
}
এখানে Authorization header চেক করা হচ্ছে, যা JWT টোকেন ধারণ করে।
4. Custom Filter Debugging
যদি আপনি কাস্টম ফিল্টার ব্যবহার করেন (যেমন custom authentication filter বা custom authorization filter), তাহলে সেই ফিল্টারগুলো ডিবাগ করতে পারেন। উদাহরণস্বরূপ, আপনার কাস্টম ফিল্টারে লগ প্রিন্ট করতে পারেন:
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
public class CustomAuthenticationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Custom Filter Initialized");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("Custom Filter Applied");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("Custom Filter Destroyed");
}
}
এটি কাস্টম ফিল্টারের মাধ্যমে টেস্ট বা ডিবাগ করার সময় লগ প্রিন্ট করবে।
উপসংহার
Spring Security এর Testing এবং Debugging হলো নিরাপত্তা সংক্রান্ত যে কোনো সমস্যা দ্রুত চিহ্নিত ও সমাধান করার জন্য গুরুত্বপূর্ণ দুটি পদক্ষেপ। Integration Testing এর মাধ্যমে আপনি নিশ্চিত করতে পারেন যে আপনার নিরাপত্তা ফিচারগুলি সঠিকভাবে কাজ করছে, এবং Debugging এর মাধ্যমে আপনি বিস্তারিত লগ দেখতে পারেন, যা আপনাকে নিরাপত্তা সম্পর্কিত ত্রুটি সমাধানে সহায়ক হবে।
স্প্রিং সিকিউরিটি প্রোজেক্টে Unit এবং Integration Testing খুবই গুরুত্বপূর্ণ। সঠিকভাবে সিকিউরিটি কনফিগারেশন এবং অথেন্টিকেশন-অথরাইজেশন ফিচারগুলো পরীক্ষা না করলে, অ্যাপ্লিকেশনের সিকিউরিটি ঝুঁকির মুখে পড়তে পারে। এই টেস্টিং পদ্ধতিগুলোর মাধ্যমে আমরা নিশ্চিত করতে পারি যে সিকিউরিটি কনফিগারেশন সঠিকভাবে কাজ করছে।
এখানে আমরা আলোচনা করব কিভাবে Unit Testing এবং Integration Testing স্প্রিং সিকিউরিটির জন্য করা যায়।
১. Unit Testing for Spring Security
Unit Testing মূলত সুনির্দিষ্ট একটি মেথড বা ক্লাসের লজিক পরীক্ষার জন্য ব্যবহৃত হয়। স্প্রিং সিকিউরিটি ব্যবহার করার সময়, আমরা সাধারনত AuthenticationManager, UserDetailsService, এবং SecurityContext টেস্ট করি।
উদাহরণ: UserDetailsService এর ইউনিট টেস্ট
@RunWith(MockitoJUnitRunner.class)
public class UserDetailsServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private CustomUserDetailsService userDetailsService;
@Test
public void testLoadUserByUsername() {
// Mocking database return value
User mockUser = new User("user", "{noop}password", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
when(userRepository.findByUsername("user")).thenReturn(Optional.of(mockUser));
// Test the UserDetailsService method
UserDetails userDetails = userDetailsService.loadUserByUsername("user");
// Assertions
assertEquals("user", userDetails.getUsername());
assertEquals("{noop}password", userDetails.getPassword());
assertTrue(userDetails.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_USER")));
}
}
এখানে CustomUserDetailsService ক্লাসে loadUserByUsername() মেথডটিকে ইউনিট টেস্ট করা হচ্ছে। আমরা মক করা ডাটাবেস থেকে একটি ইউজার অবজেক্ট ফেরত দিয়ে তার তথ্য যাচাই করেছি।
২. Integration Testing for Spring Security
Integration Testing হলো পুরো অ্যাপ্লিকেশনের অংশগুলোর (যেমন, ডাটাবেস, সার্ভিসেস, কন্ট্রোলার ইত্যাদি) মধ্যে ইন্টারঅ্যাকশন পরীক্ষা করা। স্প্রিং সিকিউরিটি কনফিগারেশন সহ ইন্টিগ্রেশন টেস্টিং করা খুবই গুরুত্বপূর্ণ, কারণ এতে সিকিউরিটি ফিল্টার, অথেন্টিকেশন, অথরাইজেশন এবং অন্যান্য সিকিউরিটি ফিচারগুলো পরীক্ষা করা যায়।
উদাহরণ: Integration Test for Secured Endpoint
ধরা যাক, আমাদের একটি সিকিউরড GET /user/{id} এন্ডপয়েন্ট রয়েছে, যেখানে কেবলমাত্র অথেন্টিকেটেড ব্যবহারকারীরা অ্যাক্সেস পেতে পারেন। এখানে আমরা এই এন্ডপয়েন্টের ইন্টিগ্রেশন টেস্টিং করব।
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserRepository userRepository;
@Test
public void testGetUserByIdWithValidUser() throws Exception {
User mockUser = new User("user", "{noop}password", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));
mockMvc.perform(get("/user/1")
.with(user("user").password("{noop}password").roles("USER")))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username").value("user"));
}
@Test
public void testGetUserByIdWithInvalidUser() throws Exception {
mockMvc.perform(get("/user/1")
.with(user("user").password("{noop}password").roles("USER")))
.andExpect(status().isUnauthorized());
}
}
এখানে, MockMvc ব্যবহার করে আমরা HTTP রিকোয়েস্ট পাঠাচ্ছি এবং সিকিউরড এন্ডপয়েন্টটি পরীক্ষা করছি।
/user/1এন্ডপয়েন্টটি শুধুমাত্র অথেন্টিকেটেড ইউজারদের জন্যই অ্যাক্সেসযোগ্য।- প্রথম টেস্টে, একটি বৈধ ব্যবহারকারী (যার ইউজারনেম "user" এবং পাসওয়ার্ড
{noop}password) রিকোয়েস্ট পাঠালে 200 OK স্ট্যাটাস কোড এবং ইউজারের তথ্য রিটার্ন হবে। - দ্বিতীয় টেস্টে, যদি ব্যবহারকারী অননুমোদিত হয়, তবে 401 Unauthorized রিটার্ন হবে।
৩. Remember-Me Authentication এর Integration Test
আমরা যদি Remember-Me Authentication কনফিগার করি, তাহলে এটি টেস্ট করার জন্য একটি ইন্টিগ্রেশন টেস্টের উদাহরণ দেখানো হলো:
@SpringBootTest
@AutoConfigureMockMvc
public class RememberMeIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testRememberMeFunctionality() throws Exception {
mockMvc.perform(formLogin("/login").user("user").password("{noop}password").param("remember-me", "true"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/home"));
// Now, send another request after some time to check remember-me functionality
mockMvc.perform(get("/home"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("Welcome, user")));
}
}
এখানে, প্রথমে একটি Remember-Me ফর্ম লগইন করা হয়েছে এবং দ্বিতীয় রিকোয়েস্টে ইউজারকে আবার লগইন না করেই হোম পেজে প্রবেশ করতে দেওয়া হয়েছে।
৪. Testing Security Context
স্প্রিং সিকিউরিটির SecurityContext টেস্ট করা অত্যন্ত গুরুত্বপূর্ণ, কারণ এটি ইউজারের অথেন্টিকেশন এবং অথরাইজেশন তথ্য ধারণ করে।
@Test
public void testSecurityContext() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
assertNotNull(authentication);
assertEquals("user", authentication.getName());
assertTrue(authentication.getAuthorities().stream()
.anyMatch(authority -> authority.getAuthority().equals("ROLE_USER")));
}
এই টেস্টটি নিশ্চিত করবে যে SecurityContext সঠিকভাবে ইউজারের তথ্য ধারণ করছে এবং এটি যথাযথভাবে অথরিটি যাচাই করছে।
উপসংহার:
- Unit Testing-এ সাধারণত মেথড বা সেবা স্তরের সিকিউরিটি পরীক্ষা করা হয়, যেমন UserDetailsService, AuthenticationManager, এবং SecurityContext।
- Integration Testing-এ স্প্রিং সিকিউরিটি কনফিগারেশন, অথেন্টিকেশন, অথরাইজেশন এবং সিকিউরিটি ফিল্টার সিস্টেমের কার্যকারিতা পরীক্ষা করা হয়।
- স্প্রিং সিকিউরিটি অ্যানোটেশন (যেমন
@WithMockUser) এবং MockMvc ব্যবহার করে সহজেই ইন্টিগ্রেশন টেস্ট করা যায়।
Spring Security তে টেস্টিং একটি গুরুত্বপূর্ণ অংশ, কারণ এটি নিশ্চিত করতে সাহায্য করে যে নিরাপত্তা কনফিগারেশন সঠিকভাবে কাজ করছে। Spring Security টেস্টিং করার জন্য @WithMockUser এবং @WithUserDetails এনোটেশন দুটি গুরুত্বপূর্ণ সরঞ্জাম।
- @WithMockUser: এটি একটি কাস্টম ইউজার তৈরি করে যা Spring Security টেস্টিং কনটেক্সটে ব্যবহার করা হয়। এটি সাধারণত মক ইউজার তৈরি করতে ব্যবহৃত হয়, যা পাসওয়ার্ড, রোল এবং অনুমতিসমূহ সহ টেস্টিং কনফিগারেশনের জন্য ব্যবহার করা হয়।
- @WithUserDetails: এটি Spring Security-র মাধ্যমে ডাটাবেসে সংরক্ষিত ইউজার ডিটেইলস ব্যবহার করে টেস্টে ইউজার তৈরি করে। এটি
UserDetailsServiceথেকে ইউজারের তথ্য নিয়ে আসে এবং সেটি টেস্ট কেসে ব্যবহার করে।
ধাপ ১: Spring Security টেস্টিং কনফিগারেশন
প্রথমে, Spring Security টেস্টিং সমর্থন করার জন্য spring-boot-starter-test ডিপেন্ডেন্সি এবং spring-security-test ডিপেন্ডেন্সি যুক্ত করতে হবে।
pom.xml ডিপেন্ডেন্সি:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
ধাপ ২: @WithMockUser এনোটেশন
@WithMockUser এনোটেশন দিয়ে আপনি সহজেই একটি মক ইউজার তৈরি করতে পারেন। এটি কোন ইউজারের সাথে টেস্ট করতে চান তার জন্য প্রয়োজনীয় ইউজারনেম, রোল এবং পাসওয়ার্ড প্রদান করতে পারে। এটি Spring Security কনটেক্সটে ইউজারকে অস্থায়ীভাবে ইনজেক্ট করে।
উদাহরণ: @WithMockUser ব্যবহার
import org.junit.jupiter.api.Test;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SecurityTest {
private MockMvc mockMvc;
@Test
@WithMockUser(username = "admin", roles = "ADMIN")
public void testAccessSecuredEndpointWithAdmin() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
mockMvc.perform(get("/admin"))
.andExpect(status().isOk()); // Expected status for admin role
}
@Test
@WithMockUser(username = "user", roles = "USER")
public void testAccessSecuredEndpointWithUser() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
mockMvc.perform(get("/user"))
.andExpect(status().isOk()); // Expected status for user role
}
@Test
@WithMockUser(username = "guest", roles = "GUEST")
public void testAccessSecuredEndpointWithGuest() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
mockMvc.perform(get("/guest"))
.andExpect(status().isForbidden()); // Forbidden for guest role
}
}
ব্যাখ্যা:
@WithMockUser(username = "admin", roles = "ADMIN"): এই এনোটেশনটি একটি মক ইউজার তৈরি করবে যার ইউজারনেমadminএবং রোলADMIN।testAccessSecuredEndpointWithAdmin():/adminএন্ডপয়েন্টের জন্য লগইন করে, এবংADMINরোল সহ ব্যবহৃত ইউজারটিকে200 OKস্ট্যাটাস প্রদান করা হয়।testAccessSecuredEndpointWithUser():/userএন্ডপয়েন্টে ইউজারের অ্যাক্সেস অনুমোদন করা হয়, যেখানে ইউজারের রোলUSER।testAccessSecuredEndpointWithGuest():/guestএন্ডপয়েন্টেGUESTরোলের জন্য অ্যাক্সেস নিষিদ্ধ (Forbidden) করা হয়।
ধাপ ৩: @WithUserDetails এনোটেশন
@WithUserDetails এনোটেশন ব্যবহার করে Spring Security বাস্তব ইউজার ডেটাবেসে সংরক্ষিত ইউজারদের সাথে টেস্ট করতে পারে। এটি UserDetailsService থেকে ডাটা নিয়ে ইউজার তৈরি করে।
উদাহরণ: @WithUserDetails ব্যবহার
import org.junit.jupiter.api.Test;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SecurityTest {
private MockMvc mockMvc;
@Test
@WithUserDetails("admin") // UserDetailsService থেকে 'admin' ইউজার নিয়ে আসবে
public void testAccessSecuredEndpointWithAdminUserDetails() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
mockMvc.perform(get("/admin"))
.andExpect(status().isOk()); // Expected status for admin role
}
@Test
@WithUserDetails("user") // UserDetailsService থেকে 'user' ইউজার নিয়ে আসবে
public void testAccessSecuredEndpointWithUserUserDetails() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
mockMvc.perform(get("/user"))
.andExpect(status().isOk()); // Expected status for user role
}
}
ব্যাখ্যা:
@WithUserDetails("admin"): এটিUserDetailsServiceথেকেadminনামক ব্যবহারকারীকে লোড করে, এবং তার রোল, পাসওয়ার্ডসহ সঠিকভাবে টেস্টের কনটেক্সটে ইউজার ডেটা ইনজেক্ট করে।testAccessSecuredEndpointWithAdminUserDetails():/adminএন্ডপয়েন্টে ইউজারটির অ্যাক্সেস অনুমোদিত হবে, যেহেতুadminইউজারকেADMINরোল দেওয়া হয়েছে।testAccessSecuredEndpointWithUserUserDetails():/userএন্ডপয়েন্টেuserরোল সহ ইউজারের অ্যাক্সেস অনুমোদিত হবে।
ধাপ ৪: কাস্টম ইউজার ডিটেইলসের সাথে @WithUserDetails ব্যবহার
যদি আপনার প্রকল্পে একটি কাস্টম UserDetailsService থাকে, তবে @WithUserDetails ব্যবহার করতে হবে সেই কাস্টম ইউজার ডিটেইলস সার্ভিসের মাধ্যমে। এর জন্য আপনাকে @WithUserDetails এর সাথে সেই ইউজারের নাম বা UserDetailsService কনফিগার করতে হবে।
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public User loadUserByUsername(String username) throws UsernameNotFoundException {
if ("admin".equals(username)) {
return new User("admin", "password", AuthorityUtils.createAuthorityList("ROLE_ADMIN"));
} else if ("user".equals(username)) {
return new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
}
throw new UsernameNotFoundException("User not found");
}
}
এখন আপনি @WithUserDetails("admin") এনোটেশন ব্যবহার করলে এটি কাস্টম UserDetailsService থেকে ইউজারের ডিটেইলস লোড করবে।
উপসংহার
Spring Security তে @WithMockUser এবং @WithUserDetails দুটি শক্তিশালী এনোটেশন যা টেস্টিংয়ের জন্য ব্যবহৃত হয়:
- @WithMockUser: মক ইউজার তৈরি করতে ব্যবহৃত হয়, যেটি কোন ডাটাবেস ডিপেনডেন্ট নয়।
- @WithUserDetails: এটি বাস্তব ইউজারের ডিটেইলস লোড করতে ব্যবহৃত হয়, যা
UserDetailsServiceথেকে প্রাপ্ত হয় এবং ডাটাবেস ভিত্তিক ইউজার যাচাই করে।
এই দুটি এনোটেশন Spring Security কনফিগারেশনের অধীনে নিরাপত্তা টেস্টিং প্রক্রিয়া সহজতর করতে সহায়ক।
Spring Security একটি নিরাপত্তা ফ্রেমওয়ার্ক, যা ব্যবহারকারীদের অ্যাপ্লিকেশন বা API-এ সুরক্ষা প্রদান করে। তবে সঠিকভাবে কাজ করছে কিনা তা নিশ্চিত করার জন্য Spring Security-এর সঠিক testing এবং debugging অত্যন্ত গুরুত্বপূর্ণ। এখানে আমরা Spring Security এর testing এবং debugging এর জন্য কিছু পদ্ধতি এবং উদাহরণ দেখব।
Spring Security Testing
Spring Security অ্যাপ্লিকেশনের নিরাপত্তা পরীক্ষা করার জন্য বেশ কিছু টেস্টিং টুল এবং কৌশল রয়েছে। সাধারণত, JUnit এবং Spring Test ব্যবহৃত হয়, তবে আপনি Mockito এবং MockMvc এর সাহায্যেও Spring Security এর টেস্ট করতে পারেন।
1. Basic Authentication Test
MockMvc ব্যবহার করে Spring Security এর Basic Authentication টেস্ট করা যায়। এটি আপনাকে একটি HTTP রিকোয়েস্ট সিমুলেট করতে এবং সার্ভারের রেসপন্স পরীক্ষা করতে সাহায্য করে।
Dependency (Maven):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Basic Authentication Test Example:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@SpringBootTest
public class BasicAuthTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(username = "user", password = "password", roles = "USER")
public void testBasicAuth() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/secured-endpoint"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("Hello, user!"));
}
}
@WithMockUser: এটি একটি মক ইউজার তৈরি করে, যার জন্য আমরা পাসওয়ার্ড এবং রোল নির্দিষ্ট করতে পারি। এখানে আমরা"user"ব্যবহারকারী এবং"password"পাসওয়ার্ড দিয়েছি।- MockMvc: এটি HTTP রিকোয়েস্ট এবং রেসপন্স টেস্ট করতে ব্যবহৃত হয়।
2. JWT Authentication Test
JWT (JSON Web Token) ব্যবহার করে নিরাপত্তা পরীক্ষার জন্যও MockMvc ব্যবহৃত হতে পারে। এখানে JWT Token প্রেরণ করতে এবং এর ভ্যালিডেশন চেক করার জন্য কাস্টম টেস্ট কেস তৈরি করা হয়েছে।
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
public class JwtAuthenticationTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(username = "user", password = "password", roles = "USER")
public void testJwtAuth() throws Exception {
mockMvc.perform(get("/secured-endpoint")
.header("Authorization", "Bearer <valid_jwt_token>"))
.andExpect(status().isOk());
}
}
- Authorization Header: JWT টোকেন প্রেরণের জন্য Authorization হেডারে
Bearer <valid_jwt_token>পাঠানো হয়।
3. Test Authentication Failure
এটি authentication failure টেস্ট করার একটি উদাহরণ:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
public class AuthenticationFailureTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testAuthenticationFailure() throws Exception {
mockMvc.perform(get("/secured-endpoint")
.header("Authorization", "Bearer <invalid_jwt_token>"))
.andExpect(status().isUnauthorized()); // Expecting 401 Unauthorized status
}
}
এখানে, যদি আমরা একটি ভুল JWT টোকেন পাঠাই, তাহলে 401 Unauthorized রেসপন্স আসবে।
Spring Security Debugging
Spring Security এর সমস্যাগুলি ডিবাগ করার জন্য কিছু টুল এবং কৌশল রয়েছে। Debugging এর জন্য Spring Security বিশেষভাবে logging এবং debugging filters ব্যবহার করে থাকে।
1. Enable Debug Logs for Spring Security
Spring Security তে লগিং সক্ষম করতে, আপনাকে application.properties বা application.yml ফাইলে লগিং লেভেল সেট করতে হবে।
application.properties:
logging.level.org.springframework.security=DEBUG
logging.level.org.springframework.web=DEBUG
এটি Spring Security এর মধ্যে সমস্ত গুরুত্বপূর্ণ কার্যকলাপ এবং সেশন ব্যবস্থাপনা সম্পর্কিত ডিবাগ তথ্য লগ করবে।
2. Logging Authentication Process
Spring Security তে ব্যবহারকারীর প্রমাণীকরণের প্রক্রিয়া লগ করতে AuthenticationManager বা SecurityContext কে লগ করা যেতে পারে।
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
Authentication authentication = super.attemptAuthentication(request, response);
System.out.println("User authenticated: " + authentication.getName());
return authentication;
}
}
এটি authentication এর সময় ব্যবহারকারীর নাম লগ করবে।
3. Debugging with Breakpoints in IDE
Spring Security তে যদি কোনো সমস্যা থাকে, তাহলে IDE (যেমন IntelliJ IDEA বা Eclipse) তে ব্রেকপয়েন্ট সেট করে ডিবাগ করা যেতে পারে। এর মাধ্যমে আপনি SecurityContext এবং অন্যান্য গুরুত্বপূর্ণ অবজেক্টের মান দেখতে পাবেন।
Conclusion
Spring Security টেস্টিং এবং ডিবাগিং খুবই গুরুত্বপূর্ণ, কারণ এটি অ্যাপ্লিকেশনের নিরাপত্তা নিশ্চিত করে। সঠিকভাবে Spring Security টেস্ট এবং ডিবাগ করা নিশ্চিত করবে যে:
- Authentication এবং Authorization সঠিকভাবে কাজ করছে।
- সঠিক error messages এবং security logs পাওয়া যাচ্ছে।
- বিভিন্ন সিকিউরিটি সেটিংস এবং কনফিগারেশন সঠিকভাবে কাজ করছে।
Testing এর মাধ্যমে আমরা নিশ্চিত হতে পারি যে সিস্টেম সঠিকভাবে কাজ করছে এবং Debugging এর মাধ্যমে সম্ভাব্য সমস্যাগুলি চিহ্নিত করে তা সমাধান করতে পারি।
Read more